package org.zsk.cs.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.zsk.cs.dao.MenuDao;
import org.zsk.cs.dao.RoleDao;
import org.zsk.cs.domain.po.Menu;
import org.zsk.cs.domain.po.Role;
import org.zsk.cs.service.MenuService;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 安全数据源过滤用户类
 * @author zsk
 * @version 1.0
 * Create on 2019/11/14
 */
@Component
public class CustomFilterInvocationSecurityMetadataSource
        implements FilterInvocationSecurityMetadataSource {
    AntPathMatcher antPathMatcher = new AntPathMatcher();

    private final MenuDao menuDao;
    private final RoleDao roleDao;
    private final MenuService menuService;

    @Autowired
    public CustomFilterInvocationSecurityMetadataSource(MenuDao menuDao, RoleDao roleDao, MenuService menuService) {
        this.menuDao = menuDao;
        this.roleDao = roleDao;
        this.menuService = menuService;
    }

    @Override
    public Collection<ConfigAttribute> getAttributes(Object object)
            throws IllegalArgumentException {
        String requestUrl = ((FilterInvocation) object).getRequestUrl();
        List<Menu> allMenus = menuService.list();
        //所有角色名称
        Set<String> roleNameSet=allMenus
                .stream()
                .filter(menu -> {
                    return antPathMatcher.match(menu.getPattern(), requestUrl); })
                .map(Menu::getId)
                .collect(HashSet::new, (curRoleNameSet, menuId) -> {
                    //获取拥有当前权限id的角色set集合
                    curRoleNameSet.addAll(roleDao.selectRolesByMenuId(menuId)
                            .stream()
                            .map(Role::getName)
                            .collect(Collectors.toCollection(HashSet::new)));
                    },HashSet::addAll);
        if (!roleNameSet.isEmpty()){
            return SecurityConfig.createList(roleNameSet.toArray(new String[0]));
        }
        return SecurityConfig.createList("ROLE_LOGIN");
    }

    /**
     * @return
     */
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }
    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}
